package com.jorado.metrics.type;

import com.jorado.metrics.util.LabelHelp;
import com.jorado.metrics.util.VersionHelp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

public final class Summary {

    public static final Logger logger = LoggerFactory.getLogger(Summary.class);

    private ConcurrentHashMap<String, io.prometheus.client.Summary> SUMMARY = new ConcurrentHashMap<>(16);

    private static Summary INSTANCE = null;

    public static Summary getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Summary();
        }
        return INSTANCE;
    }

    public void register(String name, String help, String... labels) {
        register(name, help, false, labels);
    }

    public void register(String name, String help, boolean defaultQuantile, String... labels) {
        List<double[]> list = new ArrayList<>();
        if (defaultQuantile) {
            list.add(new double[]{0.75, 0.05});
            list.add(new double[]{0.85, 0.05});
            list.add(new double[]{0.90, 0.05});
            list.add(new double[]{0.95, 0.05});
            list.add(new double[]{0.99, 0.01});
        }
        register(name, help, list, TimeUnit.MINUTES.toSeconds(10), 5, labels);
    }

    public void register(String name, String help, List<double[]> list, String... labels) {
        register(name, help, list, TimeUnit.MINUTES.toSeconds(10), 5, labels);
    }

    public void register(String name, String help, List<double[]> list, long maxAgeSeconds, int ageBuckets, String... labels) {
        if (SUMMARY.containsKey(name)) {
            logger.error("name of " + name + " is already exist, please try another one.");
        } else {
            help += VersionHelp.Ver;
            io.prometheus.client.Summary.Builder builder = io.prometheus.client.Summary.build()
                    .maxAgeSeconds(maxAgeSeconds)
                    .ageBuckets(ageBuckets);
            if (list != null) {
                for (int i = 0; i < list.size(); i++) {
                    builder = builder.quantile(list.get(i)[0], list.get(i)[1]);
                }
                SUMMARY.put(name, builder.name(name).labelNames(LabelHelp.addLabels(labels)).help(help).register());
            } else {
                SUMMARY.put(name, builder.labelNames(LabelHelp.addLabels(labels)).help(help).register());
            }
        }
    }

    public void observe(String name, double amt, String... labelValues) {
        try {
            io.prometheus.client.Summary summary = SUMMARY.get(name);
            if (summary != null) {
                summary.labels(LabelHelp.addValues(labelValues)).observe(amt);
            } else {
                logger.error("metrics summary is null. name: " + name);
            }
        } catch (Exception e) {
            logger.error("observe", e);
        }
    }

}
